package com.sen.common.common.response;


import cn.hutool.core.util.ObjectUtil;
import com.sen.common.common.exception.ServerInvokeError;
import com.sen.common.common.exception.ServerInvokeException;
import com.sen.common.common.inter.RespCodeEnum;
import com.sen.common.common.util.JacksonUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;

/**
 * result 封装
 *
 * @author lujian
 */
@Data
@Slf4j
public class MessageResult<T> implements Serializable {

    private Head head;
    private Body<T> body;

    public MessageResult() {
    }

    private MessageResult(T data) {
        this.head = new Head();
        this.body = new Body();
        this.head.setHeadSuccess();
        this.body.setBodySuccess(data);
    }

    private MessageResult(T data, RespCodeEnum headMsgEnum, RespCodeEnum bodyMsgEnum) {
        this.head = new Head();
        this.body = new Body();
        if (ObjectUtil.isNotNull(headMsgEnum)) {
            this.head.setHeadSuccess(headMsgEnum);
        }
        if (ObjectUtil.isNotNull(bodyMsgEnum)) {
            this.body.setBody(data, bodyMsgEnum);
        }
    }

    private MessageResult(T data, Boolean success, RespCodeEnum bodyMsgEnum) {
        Head head = new Head();
        Body objectBody = new Body();
        if (success) {
            head.setHeadSuccess();
        } else {
            head.setHeadFailed();
        }
        this.head = head;
        this.body = objectBody;
        if (ObjectUtil.isNotNull(bodyMsgEnum)) {
            this.body.setBody(data, bodyMsgEnum);
        }
    }

    public static MessageResult success() {
        return new MessageResult(null);
    }

    public static <T> MessageResult success(T data) {
        return new MessageResult(data);
    }

    public static <T> MessageResult messageResult(T data, RespCodeEnum headMsgEnum, RespCodeEnum bodyMsgEnum) {
        return new MessageResult(data, headMsgEnum, bodyMsgEnum);
    }

    public static <T> MessageResult success(T data, RespCodeEnum bodyMsgEnum) {
        return new MessageResult(data, Boolean.TRUE, bodyMsgEnum);
    }

    /**
     * 请求异常
     *
     * @param headMsgEnum
     * @return
     */
    public static MessageResult reqFailed(RespCodeEnum headMsgEnum) {
        return new MessageResult(null, headMsgEnum, null);
    }

    /**
     * 请求成功，业务异常
     *
     * @param bodyMsgEnum
     * @return
     */
    public static MessageResult bizFailed(RespCodeEnum bodyMsgEnum) {
        return new MessageResult(null, Boolean.TRUE, bodyMsgEnum);
    }

    /**
     * 请求成功，业务异常
     *
     * @param bodyMsgEnum
     * @return
     */
    public static <T> MessageResult bizFailed(T data, RespCodeEnum bodyMsgEnum) {
        return new MessageResult(data, Boolean.TRUE, bodyMsgEnum);
    }

    /**
     * 在捕获异常时使用
     *
     * @param messageResult
     * @return
     */
    public static RespCodeEnum build(MessageResult messageResult) {
        if (messageResult != null) {
            if (!messageResult.getHead().getSuccess()) {
                return build(messageResult.getHead().getCode(), messageResult.getHead().getMsg(), Boolean.FALSE);
            } else {
                return build(messageResult.getBody().getCode(), messageResult.getBody().getMsg(), Boolean.FALSE);
            }
        }
        return build(500, "系统繁忙，请稍后再试", Boolean.FALSE);
    }

    /**
     * 构建respcodeenum
     *
     * @param code
     * @param msg
     * @param success
     * @return
     */
    public static RespCodeEnum build(int code, String msg, boolean success) {
        return new RespCodeEnum() {
            @Override
            public int getCode() {
                return code;
            }

            @Override
            public String getMsg() {
                return msg;
            }

            @Override
            public boolean isSuccess() {
                return success;
            }
        };
    }

    /**
     * 检查messageResult
     *
     * @param messageResult
     */
    public static void checkRemoteInvokeResult(MessageResult messageResult) {
        if (!messageResult.getHead().getSuccess()) {
            RespCodeEnum build = MessageResult.build(messageResult.getHead().getCode(), messageResult.getHead().getMsg(), messageResult.getHead().getSuccess());
            log.error(JacksonUtils.toJSONString(build));
            throw new ServerInvokeError(build);
        }
        if (!messageResult.getBody().getSuccess()) {
            RespCodeEnum build = MessageResult.build(messageResult.getBody().getCode(), messageResult.getBody().getMsg(), messageResult.getBody().getSuccess());
            log.error(JacksonUtils.toJSONString(build));
            throw new ServerInvokeError(build);
        }
    }

    /**
     * 检查messageResult
     *
     * @param messageResult
     */
    public static void checkRemoteInvokeResultOrThrowException(MessageResult messageResult) throws ServerInvokeException {
        if (!messageResult.getHead().getSuccess()) {
            RespCodeEnum build = MessageResult.build(messageResult.getHead().getCode(), messageResult.getHead().getMsg(), messageResult.getHead().getSuccess());
            log.error(JacksonUtils.toJSONString(build));
            throw new ServerInvokeException(build);
        }
        if (!messageResult.getBody().getSuccess()) {
            RespCodeEnum build = MessageResult.build(messageResult.getBody().getCode(), messageResult.getBody().getMsg(), messageResult.getBody().getSuccess());
            log.error(JacksonUtils.toJSONString(build));
            throw new ServerInvokeException(build);
        }
    }

    /**
     * 判断调用结果
     *
     * @param messageResult
     * @return
     */
    public static boolean checkRemoteResult(MessageResult messageResult) {
        return messageResult.getHead().getSuccess() && messageResult.getBody().getSuccess();
    }
}